#ifndef __STREAM_H_2010_07_22_20_25_43
#define __STREAM_H_2010_07_22_20_25_43

#define byte unsigned char
class raw_stream
{
public:
	enum e_seek_orintation
	{
		SEEK_SET, SEEK_CUR, SEEK_END
	};
private:
	byte*	m_buffer;
	size_t	m_capacity;
	size_t	m_cur_pos;
	bool	m_rev_order;
public:
	raw_stream(byte* buffer, int capacity, bool rev_order = false)
		: m_buffer(buffer), m_capacity(capacity), m_rev_order(rev_order)
	{
	}

	size_t cur_pos() const
	{
		return m_cur_pos;
	}

	bool seek(int offset, e_seek_orintation orint = SEEK_CUR)
	{
		int new_pos = 0;

		switch(orint)
		{
		case SEEK_SET:
			{
				new_pos = offset;
				break;
			}
		case SEEK_CUR:
			{
				new_pos = (int)m_cur_pos + offset;
				break;
			}
		case SEEK_END:
			{
				new_pos = (int)m_capacity + offset;
				break;
			}
		}

		if (new_pos < 0 || new_pos > (int)m_capacity)
			return false;

		m_cur_pos = (size_t)new_pos;
		return true;
	}

	template<typename T>
	bool put_item(T item)
	{
		if (m_cur_pos + sizeof(item) >= m_capacity)
			return false;

		if (sizeof(T) > sizeof(byte))
		{
			if (!m_rev_order)
				memcpy(m_buffer + m_cur_pos, item, sizeof item);
			else
				for (size_t i = 0; i < sizeof item; ++i)
					*(m_buffer + m_cur_pos + i) = *((byte*)&item + sizeof(item) - i -1);
		}
		else
			*(m_buffer + m_cur_pos) = item;

		m_cur_pos += sizeof item;

		return true;
	}

	template<typename T>
	bool get_item(T& item)
	{
		if (m_cur_pos + sizeof(item) >= m_capacity)
			return false;
		if (sizeof(T) > sizeof(byte))
		{
			if (!m_rev_order)
				memcpy((byte*)&item, m_buffer + m_cur_pos, sizeof(item));
			else
				for (size_t i = 0; i < sizeof(T); ++i)
					*((byte*)&item + sizeof(T) - i - 1) = *(m_buffer + m_cur_pos + i)
		}
		else
			*item = *(m_buffer + m_cur_pos);

		m_cur_pos += sizeof(T);

		return true;
	}

	bool put_item(const byte* item_ptr, size_t len)
	{
		if (len <= 0)
			return false;

		if (m_cur_pos + len >= m_capacity)
			return false;

		memcpy(m_buffer + m_cur_pos, item_ptr, len);
		m_cur_pos += len;

		return true;
	}

	bool put_item(const string& str_item)
	{
		if (m_cur_pos + sizeof(size_t) + str_item.size() >= m_capacity)
			return false;

		put_item(str_item.size());
		put_item((const byte*)str_item.c_str(), str_item.size());

		return true;
	}

	bool get_item(byte* item_ptr, size_t len)
	{
		if (len <= 0)
			return false;

		if (m_cur_pos + len >= m_capacity)
			return false;

		memcpy(item_ptr, m_buffer + m_cur_pos, len);
		m_cur_pos += len;

		return true;
	}

	bool get_item(string& str_item)
	{
		size_t len;
		if (!get_item(len))
			return false;

		str_item.resize(len);
		return get_item((byte*)&str_item[0], len);
	}
};
#endif